﻿namespace UnityEditorInternal
{
    using System;
    using System.Collections.Generic;
    using UnityEditor;
    using UnityEngine;

    [Serializable]
    internal class ProfilerHierarchyGUI
    {
        private static int hierarchyViewHash = "HierarchyView".GetHashCode();
        private const float kBaseIndent = 8f;
        private const int kFirst = -999999;
        private const float kFoldoutSize = 14f;
        private const float kIndent = 16f;
        private const int kLast = 0xf423f;
        private const float kRowHeight = 16f;
        private const float kScrollbarWidth = 16f;
        private const float kSmallMargin = 4f;
        private string[] m_ColumnNames;
        private string m_ColumnSettingsName;
        private ProfilerColumn[] m_ColumnsToShow;
        private bool m_DetailPane;
        private string m_DetailViewSelectedProperty = string.Empty;
        private int m_DoScroll;
        private SerializedStringTable m_ExpandedHash = new SerializedStringTable();
        private int m_ScrollViewHeight;
        private int m_SelectedIndex = -1;
        private ProfilerColumn m_SortType = ProfilerColumn.TotalTime;
        private SplitterState m_Splitter;
        private int[] m_SplitterMinWidths;
        private float[] m_SplitterRelativeSizes;
        private Vector2 m_TextScroll = Vector2.zero;
        private bool[] m_VisibleColumns;
        private IProfilerWindowController m_Window;
        private static Styles ms_Styles;

        public ProfilerHierarchyGUI(IProfilerWindowController window, string columnSettingsName, ProfilerColumn[] columnsToShow, string[] columnNames, bool detailPane, ProfilerColumn sort)
        {
            this.m_Window = window;
            this.m_ColumnNames = columnNames;
            this.m_ColumnSettingsName = columnSettingsName;
            this.m_ColumnsToShow = columnsToShow;
            this.m_DetailPane = detailPane;
            this.m_SortType = sort;
            if (columnsToShow.Length != columnNames.Length)
            {
                throw new ArgumentException("Number of columns to show does not match number of column names.");
            }
            this.m_SplitterRelativeSizes = new float[this.m_ColumnNames.Length];
            this.m_SplitterMinWidths = new int[this.m_ColumnNames.Length];
            for (int i = 0; i < this.m_SplitterRelativeSizes.Length; i++)
            {
                this.m_SplitterMinWidths[i] = 50;
                this.m_SplitterRelativeSizes[i] = 70f;
            }
            if (this.m_ColumnsToShow[0] == ProfilerColumn.FunctionName)
            {
                this.m_SplitterRelativeSizes[0] = 400f;
                this.m_SplitterMinWidths[0] = 100;
            }
            this.m_Splitter = new SplitterState(this.m_SplitterRelativeSizes, this.m_SplitterMinWidths, null);
            this.m_VisibleColumns = new bool[columnNames.Length];
            for (int j = 0; j < this.m_VisibleColumns.Length; j++)
            {
                this.m_VisibleColumns[j] = true;
            }
            string str = EditorPrefs.GetString(columnSettingsName);
            for (int k = 0; k < columnNames.Length; k++)
            {
                if ((k < str.Length) && (str[k] == '0'))
                {
                    this.SetColumnVisible(k, false);
                }
            }
        }

        private bool ColIsVisible(int index)
        {
            return (((index >= 0) && (index <= this.m_VisibleColumns.Length)) && this.m_VisibleColumns[index]);
        }

        private void ColumnContextClick(object userData, string[] options, int selected)
        {
            this.SetColumnVisible(selected, !this.ColIsVisible(selected));
        }

        private static string DetailViewSelectedPropertyPath(ProfilerProperty property)
        {
            if (((property != null) && (property.instanceIDs != null)) && ((property.instanceIDs.Length != 0) && (property.instanceIDs[0] != 0)))
            {
                return DetailViewSelectedPropertyPath(property, property.instanceIDs[0]);
            }
            return string.Empty;
        }

        private static string DetailViewSelectedPropertyPath(ProfilerProperty property, int instanceId)
        {
            return (property.propertyPath + "/" + instanceId);
        }

        public void DoGUI(ProfilerProperty property)
        {
            this.DoScrolling();
            int controlID = GUIUtility.GetControlID(hierarchyViewHash, FocusType.Passive);
            this.DrawColumnsHeader();
            this.m_TextScroll = EditorGUILayout.BeginScrollView(this.m_TextScroll, ms_Styles.background);
            int rowCount = this.DrawProfilingData(property, controlID);
            property.Cleanup();
            this.UnselectIfClickedOnEmptyArea(rowCount);
            if (Event.current.type == EventType.Repaint)
            {
                this.m_ScrollViewHeight = (int) GUIClip.visibleRect.height;
            }
            GUILayout.EndScrollView();
            this.HandleKeyboard(controlID);
        }

        private void DoScroll()
        {
            this.m_DoScroll = 2;
        }

        private void DoScrolling()
        {
            if (this.m_DoScroll > 0)
            {
                this.m_DoScroll--;
                if (this.m_DoScroll == 0)
                {
                    float max = 16f * this.m_SelectedIndex;
                    float min = (max - this.m_ScrollViewHeight) + 16f;
                    this.m_TextScroll.y = Mathf.Clamp(this.m_TextScroll.y, min, max);
                }
                else
                {
                    this.m_Window.Repaint();
                }
            }
        }

        private void DrawColumnsHeader()
        {
            bool flag = false;
            GUILayout.BeginHorizontal(new GUILayoutOption[0]);
            if ((Event.current.type == EventType.MouseDown) && (Event.current.button == 1))
            {
                flag = true;
                Event.current.type = EventType.Used;
            }
            SplitterGUILayout.BeginHorizontalSplit(this.m_Splitter, EditorStyles.toolbar, new GUILayoutOption[0]);
            for (int i = 0; i < this.m_ColumnNames.Length; i++)
            {
                this.DrawTitle(new GUIContent(this.m_ColumnNames[i]), i);
            }
            SplitterGUILayout.EndHorizontalSplit();
            GUILayoutOption[] options = new GUILayoutOption[] { GUILayout.Width(16f) };
            GUILayout.Box(string.Empty, ms_Styles.header, options);
            GUILayout.EndHorizontal();
            if (flag)
            {
                Event.current.type = EventType.MouseDown;
                this.HandleHeaderMouse(GUILayoutUtility.GetLastRect());
            }
        }

        private bool DrawProfileDataItem(ProfilerProperty property, int rowCount, bool selected, int id)
        {
            bool flag = false;
            Event current = Event.current;
            Rect rect = new Rect(1f, 16f * rowCount, GUIClip.visibleRect.width, 16f);
            Rect position = rect;
            GUIStyle style = ((rowCount % 2) != 0) ? styles.entryOdd : styles.entryEven;
            if (current.type == EventType.Repaint)
            {
                style.Draw(position, GUIContent.none, false, false, selected, false);
            }
            float left = (property.depth * 16f) + 8f;
            if (property.HasChildren)
            {
                flag = this.IsExpanded(property.propertyPath);
                GUI.changed = false;
                left -= 14f;
                Rect rect3 = new Rect(left, position.y, 14f, 16f);
                flag = GUI.Toggle(rect3, flag, GUIContent.none, styles.foldout);
                if (GUI.changed)
                {
                    this.SetExpanded(property, flag);
                }
                left += 16f;
            }
            if (current.type == EventType.Repaint)
            {
                this.DrawTextColumn(ref position, property.GetColumn(this.m_ColumnsToShow[0]), 0, (this.m_ColumnsToShow[0] != ProfilerColumn.FunctionName) ? 4f : left, selected);
                styles.numberLabel.alignment = TextAnchor.MiddleRight;
                int index = 1;
                for (int i = 1; i < this.m_VisibleColumns.Length; i++)
                {
                    if (this.ColIsVisible(i))
                    {
                        position.x += this.m_Splitter.realSizes[index - 1];
                        position.width = this.m_Splitter.realSizes[index] - 4f;
                        index++;
                        styles.numberLabel.Draw(position, property.GetColumn(this.m_ColumnsToShow[i]), false, false, false, selected);
                    }
                }
                styles.numberLabel.alignment = TextAnchor.MiddleLeft;
            }
            if ((current.type == EventType.MouseDown) && rect.Contains(current.mousePosition))
            {
                GUIUtility.hotControl = 0;
                if (!EditorGUI.actionKey)
                {
                    if (this.m_DetailPane)
                    {
                        if ((current.clickCount == 1) && (property.instanceIDs.Length > 0))
                        {
                            string str = DetailViewSelectedPropertyPath(property);
                            if (this.m_DetailViewSelectedProperty != str)
                            {
                                this.m_DetailViewSelectedProperty = str;
                                UnityEngine.Object gameObject = EditorUtility.InstanceIDToObject(property.instanceIDs[0]);
                                if (gameObject is Component)
                                {
                                    gameObject = ((Component) gameObject).gameObject;
                                }
                                EditorGUIUtility.PingObject(gameObject.GetInstanceID());
                            }
                            else
                            {
                                this.m_DetailViewSelectedProperty = string.Empty;
                            }
                        }
                        else if (current.clickCount == 2)
                        {
                            SelectObjectsInHierarchyView(property);
                            this.m_DetailViewSelectedProperty = DetailViewSelectedPropertyPath(property);
                        }
                    }
                    else if (property.propertyPath == ProfilerDriver.selectedPropertyPath)
                    {
                        this.m_Window.ClearSelectedPropertyPath();
                    }
                    else
                    {
                        this.m_Window.SetSelectedPropertyPath(property.propertyPath);
                    }
                    this.DoScroll();
                }
                else if (!this.m_DetailPane)
                {
                    this.m_Window.ClearSelectedPropertyPath();
                }
                else
                {
                    this.m_DetailViewSelectedProperty = string.Empty;
                }
                GUIUtility.keyboardControl = id;
                current.Use();
            }
            if (((selected && (GUIUtility.keyboardControl == id)) && (current.type == EventType.KeyDown)) && ((current.keyCode == KeyCode.Return) || (current.keyCode == KeyCode.KeypadEnter)))
            {
                SelectObjectsInHierarchyView(property);
            }
            return flag;
        }

        private int DrawProfilingData(ProfilerProperty property, int id)
        {
            this.m_SelectedIndex = -1;
            bool enterChildren = true;
            int rowCount = 0;
            string selectedPropertyPath = ProfilerDriver.selectedPropertyPath;
            while (property.Next(enterChildren))
            {
                string propertyPath = property.propertyPath;
                bool selected = !this.m_DetailPane ? (propertyPath == selectedPropertyPath) : ((this.m_DetailViewSelectedProperty != string.Empty) && (this.m_DetailViewSelectedProperty == DetailViewSelectedPropertyPath(property)));
                if (selected)
                {
                    this.m_SelectedIndex = rowCount;
                }
                bool flag3 = Event.current.type != EventType.Layout;
                if (flag3 & ((this.m_ScrollViewHeight == 0) || (((rowCount * 16f) <= (this.m_ScrollViewHeight + this.m_TextScroll.y)) && (((rowCount + 1) * 16f) > this.m_TextScroll.y))))
                {
                    enterChildren = this.DrawProfileDataItem(property, rowCount, selected, id);
                }
                else
                {
                    enterChildren = property.HasChildren && this.IsExpanded(propertyPath);
                }
                rowCount++;
            }
            return rowCount;
        }

        private void DrawTextColumn(ref Rect currentRect, string text, int index, float margin, bool selected)
        {
            if (index != 0)
            {
                currentRect.x += this.m_Splitter.realSizes[index - 1];
            }
            currentRect.x += margin;
            currentRect.width = this.m_Splitter.realSizes[index] - margin;
            styles.numberLabel.Draw(currentRect, text, false, false, false, selected);
            currentRect.x -= margin;
        }

        private void DrawTitle(GUIContent name, int index)
        {
            if (this.ColIsVisible(index))
            {
                ProfilerColumn column = this.m_ColumnsToShow[index];
                bool flag = this.sortType == column;
                if ((index != 0) ? GUILayout.Toggle(flag, name, styles.rightHeader, new GUILayoutOption[] { GUILayout.Width((float) this.m_SplitterMinWidths[index]) }) : GUILayout.Toggle(flag, name, styles.header, new GUILayoutOption[0]))
                {
                    this.sortType = column;
                }
            }
        }

        public ProfilerProperty GetDetailedProperty(ProfilerProperty property)
        {
            bool enterChildren = true;
            string selectedPropertyPath = ProfilerDriver.selectedPropertyPath;
            while (property.Next(enterChildren))
            {
                string propertyPath = property.propertyPath;
                if (propertyPath == selectedPropertyPath)
                {
                    ProfilerProperty property2 = new ProfilerProperty();
                    property2.InitializeDetailProperty(property);
                    return property2;
                }
                if (property.HasChildren)
                {
                    enterChildren = this.IsExpanded(propertyPath);
                }
            }
            return null;
        }

        private int[] GetVisibleDropDownIndexList()
        {
            List<int> list = new List<int>();
            for (int i = 0; i < this.m_ColumnNames.Length; i++)
            {
                if (this.m_VisibleColumns[i])
                {
                    list.Add(i);
                }
            }
            return list.ToArray();
        }

        private void HandleHeaderMouse(Rect columnHeaderRect)
        {
            Event current = Event.current;
            if (((current.type == EventType.MouseDown) && (current.button == 1)) && columnHeaderRect.Contains(current.mousePosition))
            {
                GUIUtility.hotControl = 0;
                Rect position = new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y, 1f, 1f);
                EditorUtility.DisplayCustomMenu(position, this.m_ColumnNames, this.GetVisibleDropDownIndexList(), new EditorUtility.SelectMenuItemFunction(this.ColumnContextClick), null);
                current.Use();
            }
        }

        private void HandleKeyboard(int id)
        {
            Event current = Event.current;
            if ((current.GetTypeForControl(id) == EventType.KeyDown) && (id == GUIUtility.keyboardControl))
            {
                switch (current.keyCode)
                {
                    case KeyCode.UpArrow:
                        this.MoveSelection(-1);
                        goto Label_016A;

                    case KeyCode.DownArrow:
                        this.MoveSelection(1);
                        goto Label_016A;

                    case KeyCode.RightArrow:
                        this.SetExpanded(ProfilerDriver.selectedPropertyPath, true);
                        goto Label_016A;

                    case KeyCode.LeftArrow:
                        this.SetExpanded(ProfilerDriver.selectedPropertyPath, false);
                        goto Label_016A;

                    case KeyCode.Home:
                        this.MoveSelection(-999999);
                        goto Label_016A;

                    case KeyCode.End:
                        this.MoveSelection(0xf423f);
                        goto Label_016A;

                    case KeyCode.PageUp:
                        if (Application.platform != RuntimePlatform.OSXEditor)
                        {
                            this.MoveSelection(-Mathf.RoundToInt(((float) this.m_ScrollViewHeight) / 16f));
                            goto Label_016A;
                        }
                        this.m_TextScroll.y -= this.m_ScrollViewHeight;
                        if (this.m_TextScroll.y < 0f)
                        {
                            this.m_TextScroll.y = 0f;
                        }
                        current.Use();
                        return;

                    case KeyCode.PageDown:
                        if (Application.platform != RuntimePlatform.OSXEditor)
                        {
                            this.MoveSelection(Mathf.RoundToInt(((float) this.m_ScrollViewHeight) / 16f));
                            goto Label_016A;
                        }
                        this.m_TextScroll.y += this.m_ScrollViewHeight;
                        current.Use();
                        return;
                }
            }
            return;
        Label_016A:
            this.DoScroll();
            current.Use();
        }

        private bool IsExpanded(string expanded)
        {
            return this.m_ExpandedHash.Contains(expanded);
        }

        private void MoveSelection(int steps)
        {
            int num = this.m_SelectedIndex + steps;
            if (num < 0)
            {
                num = 0;
            }
            ProfilerProperty property = this.m_Window.CreateProperty(this.m_DetailPane);
            if (this.m_DetailPane)
            {
                ProfilerProperty detailedProperty = this.GetDetailedProperty(property);
                property.Cleanup();
                property = detailedProperty;
            }
            if (property != null)
            {
                bool enterChildren = true;
                int num2 = 0;
                int instanceId = -1;
                while (property.Next(enterChildren))
                {
                    if ((this.m_DetailPane && (property.instanceIDs != null)) && ((property.instanceIDs.Length > 0) && (property.instanceIDs[0] != 0)))
                    {
                        instanceId = property.instanceIDs[0];
                    }
                    if (num2 == num)
                    {
                        break;
                    }
                    if (property.HasChildren)
                    {
                        enterChildren = !this.m_DetailPane && this.IsExpanded(property.propertyPath);
                    }
                    num2++;
                }
                if (this.m_DetailPane)
                {
                    this.m_DetailViewSelectedProperty = DetailViewSelectedPropertyPath(property, instanceId);
                }
                else
                {
                    this.m_Window.SetSelectedPropertyPath(property.propertyPath);
                }
                property.Cleanup();
            }
        }

        private void SaveColumns()
        {
            string str = string.Empty;
            for (int i = 0; i < this.m_VisibleColumns.Length; i++)
            {
                str = str + (!this.ColIsVisible(i) ? '0' : '1');
            }
            EditorPrefs.SetString(this.m_ColumnSettingsName, str);
        }

        private static void SelectObjectsInHierarchyView(ProfilerProperty property)
        {
            int[] instanceIDs = property.instanceIDs;
            List<UnityEngine.Object> list = new List<UnityEngine.Object>();
            foreach (int num in instanceIDs)
            {
                UnityEngine.Object item = EditorUtility.InstanceIDToObject(num);
                Component component = item as Component;
                if (component != null)
                {
                    list.Add(component.gameObject);
                }
                else if (item != null)
                {
                    list.Add(item);
                }
            }
            if (list.Count != 0)
            {
                Selection.objects = list.ToArray();
            }
        }

        private void SetColumnVisible(int index, bool enabled)
        {
            if ((index != 0) && (this.m_VisibleColumns[index] != enabled))
            {
                this.m_VisibleColumns[index] = enabled;
                int num = 0;
                for (int i = 0; i < index; i++)
                {
                    if (this.ColIsVisible(i))
                    {
                        num++;
                    }
                }
                if (enabled)
                {
                    ArrayUtility.Insert<float>(ref this.m_Splitter.relativeSizes, num, this.m_SplitterRelativeSizes[index]);
                    ArrayUtility.Insert<int>(ref this.m_Splitter.minSizes, num, this.m_SplitterMinWidths[index]);
                }
                else
                {
                    ArrayUtility.RemoveAt<float>(ref this.m_Splitter.relativeSizes, num);
                    ArrayUtility.RemoveAt<int>(ref this.m_Splitter.minSizes, num);
                }
                this.m_Splitter = new SplitterState(this.m_Splitter.relativeSizes, this.m_Splitter.minSizes, null);
                this.SaveColumns();
            }
        }

        private void SetExpanded(string expandedName, bool expanded)
        {
            if (expanded != this.IsExpanded(expandedName))
            {
                if (expanded)
                {
                    this.m_ExpandedHash.Set(expandedName);
                }
                else
                {
                    this.m_ExpandedHash.Remove(expandedName);
                }
            }
        }

        private void SetExpanded(ProfilerProperty property, bool expanded)
        {
            this.SetExpanded(property.propertyPath, expanded);
        }

        private void UnselectIfClickedOnEmptyArea(int rowCount)
        {
            GUILayoutOption[] options = new GUILayoutOption[] { GUILayout.MinHeight(16f * rowCount) };
            Rect rect = GUILayoutUtility.GetRect(GUIClip.visibleRect.width, (float) (16f * rowCount), options);
            if (((Event.current.type == EventType.MouseDown) && (Event.current.mousePosition.y > rect.y)) && (Event.current.mousePosition.y < Screen.height))
            {
                if (!this.m_DetailPane)
                {
                    this.m_Window.ClearSelectedPropertyPath();
                }
                else
                {
                    this.m_DetailViewSelectedProperty = string.Empty;
                }
                Event.current.Use();
            }
        }

        public int selectedIndex
        {
            get
            {
                return this.m_SelectedIndex;
            }
            set
            {
                this.m_SelectedIndex = value;
            }
        }

        public ProfilerColumn sortType
        {
            get
            {
                return this.m_SortType;
            }
            private set
            {
                this.m_SortType = value;
            }
        }

        private static Styles styles
        {
            get
            {
                if (ms_Styles == null)
                {
                }
                return (ms_Styles = new Styles());
            }
        }

        internal class Styles
        {
            public GUIStyle background = "OL Box";
            public GUIStyle entryEven = "OL EntryBackEven";
            public GUIStyle entryOdd = "OL EntryBackOdd";
            public GUIStyle foldout = "IN foldout";
            public GUIStyle header = "OL title";
            public GUIStyle numberLabel = "OL Label";
            public GUIStyle rightHeader = "OL title TextRight";
        }
    }
}

